iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 8
1
Modern Web

Rails guide / Ruby API study系列 第 8

[ Rails guide study ] Day08 Layout 的基本使用 (Layouts and Rendering in Rails part2)

  • 分享至 

  • xImage
  •  

首先來聽首歌吧
Yes
這是一個很年輕,我又很喜歡的台灣樂團,希望大家如果喜歡也能一起支持!


如何使用 Layout

今天從到這篇的 2.2.13 繼續看下去,這裡講到 layout 的使用方法

我們先來看看一開始 rails 的 layout 長什麼模樣

<!-- views/layouts/application.html.erb -->
<!DOCTYPE html>
<html>
  <head>
    <title>titile</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>
  <body>

      <%= yield %>

  </body>
</html>

看到這裡,不知道大家有沒有注意到在平常使用 rails view 的時候,怎麼都不用寫上面這些寫 html 的時候一定要寫的東西?就是因為它藏在 layout 裡面,平常他直接會跟著 controller ,基本上在同一個 controller 中的 layout 是一樣的,然後在 body 中才把內容 "讓" 給 view 裡面的內容渲染

那這些 layout 該放在哪裡呢?

如果你的 controller 名字叫做 CandidatesController,那麼他會去找 app/views/layouts/candidates.html.erb 這個檔案當作 layout , 如果沒有這個檔案,他會去找 app/views/layouts/application.html.erb 當作 layout,這些都是 "慣例" ,當然我們也是可以自己設定

class CandidatesController < ApplicationController
  layout "qoo"
  #...
end

利用 layout 這個方法,我們可以指定 layout 是哪個檔案,上面這個例子中就會去找 app/views/layouts/qoo.html.erb 這檔案

另外,layout 後面也可以接方法,來判斷是要使用哪一份 layout

class CandidatesController < ApplicationController
  layout :which_layout
 
  private
    def which_layout
      @current_user.login? ? "admin" : "visit"
    end
end

在上面的例子中,會去判斷 @current_user 是否登入,登入的話會使用 admin layout,否則使用 visit layout


跳回前一個來源: redirect_back

有時候我們會希望使用者回到他在進到這個頁面的前一個來源,這時候可以用 redirect_back 這個方法,在 rails 5 以前是 redirect_to :back

不過要注意的是,使用這個方法的前提是瀏覽器會回報 HTTP_REFERER 這個 error ,但有時候瀏覽器並不是丟這個 error 而是丟一個例外,這時候畫面就會爆掉,接下來說明解決方法

在 rails 5 以前解決這個問題有點麻煩,必須去抓這個例外錯誤

class CandidatesController < ApplicationController
  rescue_from ActionController::RedirectBackError, with: :redirect_to_default

  def vote
    @candidate = Candidate.find params[:id]
    @candidate.vote
    redirect_to :back
  end

  private

  def redirect_to_default
    redirect_to root_path
  end
end

上面這個例子是說,當例外發生的時候,我就把瀏覽器導至首頁

現在變得比較簡單了,可以用 fallback_location 這個方法

class CandidatesController < ApplicationController

  def vote
    @candidate = Candidate.find params[:id]
    @candidate.vote
    redirect_back(fallback_location: root_path)
  end
end

Render 跟 direct_to 的差異?

2.3 中提到,我們會在某個條件成功或失敗的情況下,使用 render 或者 redirect_to 讓使用者看到跳轉的畫面,那redirect_torender 有什麼不同?

redirect_to 是叫瀏覽器送出新的 request 給這個目的地的 url
render 則是請瀏覽器借用哪個畫面做為回應

在 2.3.2 中, Rails guide 給了一個講解的很清楚的例子,我們這裡直接借用

# redirect_to 版本
def index
  @books = Book.all
end
def show
  @book = Book.find_by(id: params[:id])
  if @book.nil?
    redirect_to action: :index
  end
end

# render 版本
def index
  @books = Book.all
end
def show
  @book = Book.find_by(id: params[:id])
  if @book.nil?
    @books = Book.all
    flash.now[:alert] = "Your book was not found"
    render "index"
  end
end

乍看之下 redirect_to 的程式碼比較簡短,但我們透過瀏覽器的角度來看看這件事情

redirect_to 版本中,我們嘗試去找這本 @book ,但發現並沒有這本書,這時候 controller 要求瀏覽器去 index 的頁面,我們轉到這個網址來,發現需要 index 的 view 跟 資料庫中的 @books 資訊,因此再去抓這些東西回來到瀏覽器上

render 版本中,我們同樣沒找到這本書,這時候 controller 請我們先抓資料庫中的 @bookd 資料,並請瀏覽器渲染出 index 的畫面,需要 @books 的地方就把資料套上去

從上面兩個說明中,應該可以知道在這個例子中 redirect_to 多繞了一圈,因此效能較差,這種情況下建議使用 render

參考資料
rails guide

Rails 5 improves redirect_to :back with new redirect_back method

本文章同步分享於 http://anthonychao.site/


上一篇
[ Rails guide study ] Day07 Render 的基本使用 (Layouts and Rendering in Rails part1)
下一篇
[ Rails guide study ] Day09 yield & content_for的使用 (Layouts and Rendering in Rails part3)
系列文
Rails guide / Ruby API study30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言